home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 526-550 / disk_540 / parm / parm_src.lzh / ParM.c < prev    next >
C/C++ Source or Header  |  1991-07-28  |  14KB  |  587 lines

  1. /*
  2.  *    ParM.c - Copyright © 1990 by S.R. & P.C.
  3.  *
  4.  *    Created:    01 Jul 1990
  5.  *    Modified:    28 Jul 1991  18:25:29
  6.  *
  7.  *    Make>> make
  8.  */
  9.  
  10. #include "ParMBase.h"
  11.  
  12.  
  13. #define COPYRIGHT "ParM V3.0 Copyright © 1990-91 by S.R. & P.C."
  14. #define DEFAULT_CONFIG_FILE "S:ParM.cfg"
  15.  
  16. #define THE_END            0
  17. #define NO_WIN            10
  18.  
  19. #define OPEN_ITEM        0
  20. #define UPDATE_ITEM        1
  21. #define STD_CFG_ITEM    2
  22. #define CMDMODE_ITEM    3
  23. #define COMMAND_ITEM    4
  24. #define CHDIR_ITEM        5
  25. #define QUIT_ITEM        6
  26.  
  27. /* ParM modes */
  28. #define MODE_CLI        0    /* default mode */
  29. #define MODE_WINDOW        1
  30. #define MODE_MYMENU        2
  31.  
  32.  
  33. extern void CreateParMenu(short Color);
  34. extern void exit(int);
  35.  
  36.  
  37. /*****                global variables                    *****/
  38.  
  39. extern struct ExecBase *SysBase;
  40. extern struct ParMBase *ParMBase;
  41. extern struct Menu Menu1;
  42. extern struct MenuItem SubItem1;
  43. extern struct WBStartup *WBenchMsg;
  44.  
  45.  
  46. /*****                 local variables                    *****/
  47.  
  48. static struct Process *ParMProcess;
  49. static struct Window *Win;
  50. static struct Menu *LastWBMenu, *TheMenu;
  51. static struct MsgPort SwapPort;
  52. static short FirstParMMenuNum;        /* = 0  if not attached to WorkBench */
  53. static short ParMMode;
  54. static ULONG OldIDCMP, WinSignal;
  55. static BOOL PortTaken;
  56. static BOOL quit;
  57. static BYTE ParMenuColor = -1;
  58. static struct FileReq FileReq;
  59. static char Dir[REQ_DSIZE+1];
  60. static char File[REQ_FCHARS+1];
  61. static char Path[REQ_DSIZE+REQ_FCHARS+2];
  62. static struct ParMConfig ParMConfig;
  63. static BOOL DoNextSelect;
  64.  
  65.  
  66. struct ToolTypesArg {
  67.     char *tta_Name;
  68.     char tta_cli_equ;
  69. };
  70.  
  71. static struct ToolTypesArg TTA_List[] = {
  72.     {"STACKSIZE",    's'},
  73.     {"LEFTEDGE",    'x'},
  74.     {"TOPEDGE",        'y'},
  75.     {"DETAILPEN",    'd'},
  76.     {"BLOCKPEN",    'b'},
  77.     {"MENUCOLOR",    'c'},
  78.     {"CONFIGFILE",    'f'},
  79.     {"NODRAGBAR",    'r'},
  80.     {"DEPTHGADGETS",'g'},
  81.     {"NOAUTOFRONT",    'a'},
  82.     {"MYMENU",        'm'}
  83. };
  84.  
  85. #define TTANUM    11        /* Number of ToolTypesArg in List */
  86.  
  87.  
  88. static struct NewWindow NWS = {
  89.     0, 0,    /* window XY origin relative to TopLeft of screen */
  90.     39, 10,    /* window width and height */
  91.     3, 2,    /* detail and block pens */
  92.     MENUPICK|RAWKEY|REFRESHWINDOW,    /* IDCMP flags */
  93.     WINDOWDRAG|SIMPLE_REFRESH,    /* other window flags */
  94.     NULL,    /* first gadget in gadget list */
  95.     NULL,    /* custom CHECKMARK imagery */
  96.     (UBYTE *)"ParM",    /* window title */
  97.     NULL,    /* custom screen pointer */
  98.     NULL,    /* custom bitmap */
  99.     5, 5,    /* minimum width and height */
  100.     -1, -1,    /* maximum width and height */
  101.     WBENCHSCREEN    /* destination screen type */
  102. };
  103.  
  104.  
  105. static struct Window *FindWorkBench(void)
  106. {
  107.     struct Screen *WBS;
  108.     struct Window *WBW = NULL;
  109.     ULONG ilock;
  110.  
  111.     if (WBS = OpenWorkBench()) {
  112.         ilock = LockIBase(0L);    /* Just so's things don't change on us */
  113.         WBW = WBS->FirstWindow;
  114.         while (WBW) {
  115.             /* Only main WB Window has NEWPREFS IDCMPFlag set, so find it */
  116.             if ((WBW->Flags & WBENCHWINDOW) && (WBW->IDCMPFlags & NEWPREFS)) {
  117.                 TheMenu = WBW->MenuStrip;
  118.                 LastWBMenu = TheMenu->NextMenu->NextMenu;
  119.                 FirstParMMenuNum = 3;
  120.                 break;
  121.             }
  122.             WBW = WBW->NextWindow;
  123.         }
  124.         UnlockIBase(ilock);
  125.     }
  126.     return WBW;
  127. }
  128.  
  129.  
  130. void TakeMsgPort(void)
  131. {
  132.     struct MsgPort *WinPort;
  133.     struct List *myMsgList = &(SwapPort.mp_MsgList);
  134.     struct List *winMsgList;
  135.  
  136.     SwapPort.mp_Node.ln_Type = NT_MSGPORT;
  137.     SwapPort.mp_Flags = PA_SIGNAL;
  138.     Forbid();
  139.  
  140.     /* get the info we need */
  141.     WinPort = Win->UserPort;
  142.     winMsgList = &(WinPort->mp_MsgList);
  143.  
  144.     /* setup our port */
  145.     SwapPort.mp_SigBit = WinPort->mp_SigBit;
  146.     SwapPort.mp_SigTask = WinPort->mp_SigTask;
  147.  
  148.     /* flip things around */
  149.     WinPort->mp_SigTask = (struct Task *)ParMProcess;
  150.     /* Prevent signal for being allocated later */
  151.     WinSignal = AllocSignal(WinPort->mp_SigBit);
  152.     myMsgList->lh_Head = (struct Node *) &winMsgList->lh_Tail;
  153.     myMsgList->lh_TailPred = winMsgList->lh_TailPred;
  154.     winMsgList->lh_TailPred = (struct Node *) &myMsgList->lh_Head;
  155.     myMsgList->lh_TailPred->ln_Succ = (struct Node *) &myMsgList->lh_Tail;
  156.  
  157.     Permit();
  158.  
  159.     /* prevent deadlocks */
  160.     SetTaskPri((struct Task *)ParMProcess, SwapPort.mp_SigTask->tc_Node.ln_Pri + 1);
  161. }
  162.  
  163.  
  164. /* Restore things the way they were before TakeMsgPort() */
  165.  
  166. void DelMsgPort(void)
  167. {
  168.     struct Message *Msg;
  169.     struct List *myMsgList = &(SwapPort.mp_MsgList);
  170.  
  171.     Forbid();
  172.     /* clean out our list */
  173.     while (Msg = GetMsg(&SwapPort))
  174.         PutMsg(&SwapPort, Msg);
  175.     /* restore things */
  176.     myMsgList->lh_Head->ln_Pred = myMsgList->lh_TailPred;
  177.     myMsgList->lh_TailPred->ln_Succ = myMsgList->lh_Head;
  178.     Win->UserPort->mp_SigTask = SwapPort.mp_SigTask;
  179.     if (WinSignal)
  180.         FreeSignal(WinSignal);
  181.     Permit();
  182. }
  183.  
  184.  
  185. /* Configuration managing functions  */
  186.  
  187. static void InstallWBMenus(struct Menu *Menus)
  188. {
  189.     long ilock;
  190.  
  191.     ilock = LockIBase(0);
  192.     ClearMenuStrip(Win);
  193.     if (Menus)
  194.         CleanUp(TheMenu, 0, ParMConfig.ItemHeight);
  195.     LastWBMenu->NextMenu = Menus;
  196.     SetMenuStrip(Win, TheMenu);
  197.     UnlockIBase(ilock);
  198. }
  199.  
  200.  
  201. static void ClearMenus(void)
  202. {
  203.     if (ParMMode == MODE_MYMENU) {
  204.         InstallWBMenus(NULL);
  205.         Menu1.LeftEdge = LastWBMenu->LeftEdge + LastWBMenu->Width;
  206.     }
  207.     else
  208.         ClearMenuStrip(Win);
  209. }
  210.  
  211.  
  212. void UpDateMenus(void)
  213. {
  214.     ClearMenus();
  215.     ParMConfig.MenuPen = ParMenuColor;
  216.     if (!ParseMenus(&ParMConfig))
  217.         FreeMenus(&ParMConfig);
  218.     if (ParMMode == MODE_MYMENU)
  219.         InstallWBMenus(&Menu1);
  220.     else
  221.         SetMenuStrip(Win, &Menu1);
  222. }
  223.  
  224.  
  225. static void OpenMenus(void)
  226. {
  227.     char *yuck;
  228.  
  229.     FileReq.Title = "Open";
  230.     strcpy(Dir, ParMConfig.CurCfg);
  231.     strcpy(File, yuck = BaseName(Dir));
  232.     *yuck = '\0';        /* cut off filename from fr_Dir */
  233.     if (!FileRequester(&FileReq))
  234.         return;    /* quit if Open canceled */
  235.     strcpy(ParMConfig.CurCfg, Path);
  236.     UpDateMenus();
  237. }
  238.  
  239.  
  240. /* Print busy message in place of window title */
  241.  
  242. static void Busy(BOOL status)
  243. {
  244.     SetWindowTitles(Win, (status) ? "Busy" : "ParM", COPYRIGHT);
  245. }
  246.  
  247.  
  248. static void Usage(void)
  249. {
  250.     Printf("%s\nUsage: ParM [-m] [-w] [-x#] [-y#] [-d#] [-b#] [-c#] [-r] [-g] [-a] [-o] [-s#] [-fConfigFile]\n", COPYRIGHT);
  251.     exit(0);
  252. }
  253.  
  254.  
  255. /* Atcho, bonsoir...  */
  256.  
  257. void Bye(short err)
  258. {
  259.     if (err == THE_END) {
  260.         ClearMenus();
  261.         FreeMenus(&ParMConfig);
  262.         if (PortTaken)
  263.             DelMsgPort();
  264.         if (ParMMode == MODE_CLI)
  265.             ModifyIDCMP(Win, OldIDCMP);
  266.         else if (ParMMode == MODE_WINDOW)
  267.             CloseWindowSafely(Win, NULL);
  268.     }
  269.     exit(err);
  270. }
  271.  
  272.  
  273. /* change parm current directory */
  274.  
  275. static void ChangeDir(char *dir)
  276. {
  277.     BPTR NewLock, OldLock;
  278.  
  279.     NewLock = Lock(dir, ACCESS_READ);
  280.     if (NewLock != NULL) {
  281.         OldLock = CurrentDir(NewLock);
  282.         if (OldLock != NULL)
  283.             UnLock(OldLock);
  284.     }
  285. }
  286.  
  287.  
  288. static void DoExtMenu(USHORT MenuNum)
  289. {
  290.     struct Extended_MenuItem *Item;
  291.     struct Extended_WBStartup *EWBS;
  292.  
  293.     Item = (struct Extended_MenuItem *)ItemAddress(TheMenu, MenuNum);
  294.     switch (Item->emi_Mode) {
  295.     case TOK_ARUN:
  296.         ARun(&ParMConfig, &Item->emi_RunInfo);
  297.         break;
  298.     case TOK_RUN:
  299.     case TOK_SHELL:
  300.         Run(&ParMConfig, &Item->emi_RunInfo, Item->emi_Mode);
  301.         break;
  302.     case TOK_WB:
  303.         if (EWBS = MakeWBStartup(&ParMConfig, &Item->emi_RunInfo))
  304.             WBRun(&ParMConfig, EWBS, Item->emi_RunInfo.ri_Pri);
  305.         break;
  306.     case TOK_CFG:    /* new cfg */
  307.         strcpy(ParMConfig.CurCfg, Item->emi_RunInfo.ri_Cmd);
  308.         UpDateMenus();
  309.         DoNextSelect = FALSE;    /* Tell DoIntuiMsg not to execute next menu selection */
  310.     }
  311. }
  312.  
  313.  
  314. static void parse_arg(char opt, char *args)
  315. {
  316.     BPTR fh;
  317.     long argl;
  318.  
  319.     argl = Atol(args);
  320.     switch (opt) {
  321.     case 'm':
  322.         ParMMode = MODE_MYMENU;
  323.         break;
  324.     case 'w':
  325.         ParMMode = MODE_WINDOW;
  326.         break;
  327.     case 's':
  328.         if (argl >= 4000) ParMConfig.DefaultStack = argl;
  329.         break;
  330.     case 'x':
  331.         NWS.LeftEdge = argl;
  332.         ParMMode = MODE_WINDOW;
  333.         break;
  334.     case 'y':
  335.         NWS.TopEdge = argl;
  336.         ParMMode = MODE_WINDOW;
  337.         break;
  338.     case 'd':
  339.         NWS.DetailPen = argl;
  340.         ParMMode = MODE_WINDOW;
  341.         break;
  342.     case 'b':
  343.         NWS.BlockPen = argl;
  344.         ParMMode = MODE_WINDOW;
  345.         break;
  346.     case 'c':
  347.         ParMenuColor = argl;
  348.         break;
  349.     case 'f':
  350.         strcpy(ParMConfig.CurCfg, args);
  351.         break;
  352.     case 'r':    /* no drag bar */
  353.         ParMMode = MODE_WINDOW;
  354.         NWS.Flags &= ~WINDOWDRAG;
  355.         break;
  356.     case 'g':    /* depth gadgets */
  357.         ParMMode = MODE_WINDOW;
  358.         NWS.Flags |= WINDOWDEPTH;
  359.         NWS.Width += 51;
  360.         break;
  361.     case 'a':
  362.         ParMMode = MODE_WINDOW;
  363.         NWS.Flags |= NOCAREREFRESH;
  364.         break;
  365.     case 'o':
  366.         if ((fh = Open("NULL:", MODE_NEWFILE)) || (fh = Open("NIL:", MODE_NEWFILE))) {
  367.             ParMProcess->pr_CIS = fh;
  368.             ParMProcess->pr_COS = fh;
  369.             ParMProcess->pr_ConsoleTask = (APTR)((struct FileHandle *)(fh<<2))->fh_Type;
  370.         }
  371.         break;
  372.     case 'h':    /* those can only happen on CLI invocation */
  373.     default:
  374.         Usage();
  375.     }
  376. }
  377.  
  378.  
  379. void main(int argc, char *argv[])
  380. {
  381.     struct CommandLineInterface *cli;
  382.     struct DiskObject *dop;
  383.     struct MsgPort *WorkPort;
  384.     struct IntuiMessage *IMsg;
  385.     ULONG Class;
  386.     USHORT Code,Qual;
  387.     BOOL RefreshIt = TRUE;
  388.     char *arg;
  389.     short i;
  390.  
  391.     TheMenu = &Menu1;
  392.     InitDefaults(&ParMConfig);
  393.     ParMConfig.ReqTitle = "ParM Request";
  394.     ParMConfig.LinkMenu = &Menu1;
  395.     ParMConfig.ItemHeight = 10;            /* 9 in BrowserII */
  396.     ParMConfig.SimpleCmdMode = TRUE;
  397.     FileReq.Dir = Dir;
  398.     FileReq.File = File;
  399.     FileReq.PathName = Path;
  400.     FileReq.dirnamescolor = 3;
  401.     FileReq.devicenamescolor = 3;
  402.     FileReq.stringnamecolor = 2;
  403.     FileReq.stringgadgetcolor = 2;
  404.     FileReq.boxbordercolor = 2;
  405.     FileReq.gadgetboxcolor = 2;
  406.     strcpy(FileReq.Show, "*.cfg");
  407.     ParMProcess = (struct Process *)SysBase->ThisTask;
  408.     strcpy(ParMConfig.CurCfg, DEFAULT_CONFIG_FILE);
  409.  
  410.     if (WBenchMsg) {    /* Tool Types parsing */
  411.         ParMMode == MODE_WINDOW;    /* may be latter overridden by MYMENU mode */
  412.         if (dop = GetDiskObject(WBenchMsg->sm_ArgList->wa_Name)) {
  413.             ParMConfig.DefaultStack = dop->do_StackSize;
  414.             for( i = 0 ; i < TTANUM ; i++ ) {
  415.                 if (arg = FindToolType(dop->do_ToolTypes, TTA_List[i].tta_Name))
  416.                     parse_arg(TTA_List[i].tta_cli_equ, arg);
  417.             }
  418.             FreeDiskObject(dop);
  419.         }
  420.         parse_arg('o', "");        /* allways redirect output to NULL: if started from WorkBench */
  421.     }
  422.     else {    /* CLI parsing */
  423.         cli = (struct CommandLineInterface *)((long)ParMProcess->pr_CLI << 2);
  424.         ParMConfig.DefaultStack = cli->cli_DefaultStack << 2;
  425.         for( i = 0 ; i < argc ; i++ ) {
  426.             if (*argv[i] != '-' || strlen(argv[i]) < 2)
  427.                 Usage();
  428.             parse_arg(argv[i][1], &argv[i][2]);
  429.         }
  430.     }
  431.     switch(ParMMode) {
  432.     case MODE_WINDOW:
  433.         if (!(Win = OpenWindow(&NWS)))
  434.             Bye(NO_WIN);
  435.         Busy(FALSE);    /* SetWindowTitles() */
  436.         break;
  437.     case MODE_CLI:
  438.         Win = GetWindow();
  439.         if (Win->UserPort) {
  440.             if (Win->IDCMPFlags & MENUPICK) {
  441.                 SimpleRequest(ParMConfig.ReqTitle, "This window already have menus.");
  442.                 Bye(NO_WIN);
  443.             }
  444.             else {
  445.                 PortTaken = TRUE;
  446.                 OldIDCMP = Win->IDCMPFlags;
  447.             }
  448.         }
  449.         ModifyIDCMP(Win, Win->IDCMPFlags|MENUPICK|CLOSEWINDOW);
  450.         break;
  451.     case MODE_MYMENU:
  452.         if (Win = FindWorkBench()) {
  453.             if (LastWBMenu->NextMenu) {
  454.                 SimpleRequest(ParMConfig.ReqTitle, "Menus already installed in WorkBench.");
  455.                 Bye(NO_WIN);
  456.             }
  457.             else
  458.                 PortTaken = TRUE;
  459.         }
  460.         else {
  461.             SimpleRequest(ParMConfig.ReqTitle, "Can't find WorkBench.");
  462.             Bye(NO_WIN);
  463.         }
  464.     }
  465.     ParMConfig.Win = Win;
  466.     if (PortTaken)
  467.         TakeMsgPort();
  468.     if (ParMenuColor < 0) ParMenuColor = Win->DetailPen;
  469.     CreateParMenu(ParMenuColor);
  470.     UpDateMenus();
  471.  
  472.     /* Monitor Menu Events */
  473.  
  474.     WorkPort = (PortTaken) ? &SwapPort : Win->UserPort;
  475.     while (!quit) {
  476.         WaitPort(WorkPort);
  477.         while (IMsg = (struct IntuiMessage *)GetMsg(WorkPort)) {
  478.             Class = IMsg->Class;
  479.             Code = IMsg->Code;
  480.             Qual = IMsg->Qualifier;
  481.             /* Use raw keys to prevent ALT and CTRL convertions. Allow only Shift qualifiers */
  482.             if (Class == RAWKEY) {
  483.                 Code = RawKeyToAscii(Code, Qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT), IMsg->IAddress);
  484.                 if (Code != 0 && (Qual & ParMConfig.ShortCutQual) && !(Qual & IEQUALIFIER_REPEAT)) {
  485.                     Code = MakeMenuShortCut(TheMenu, Code);
  486.                     Class = MENUPICK;
  487.                 }
  488.             }
  489.             /*
  490.              *    PutMsg() conditions (Messages given to port monitored):
  491.              *    MODE_WINDOW:
  492.              *        No such port, so all messages replied.
  493.              *    MODE_MYMENU:
  494.              *        give all messages but ParM's menus MENUPICK and RAWKEYs converted
  495.              *        to MENUPICK. handle NEWPREFS after PutMsg().
  496.              *    MODE_CLI:
  497.              *        if PortTaken, all but MENUPICK and CLOSEWINDOW.
  498.              */
  499.             if (!PortTaken
  500.                 || (Class == MENUPICK && (MENUNUM(Code) >= FirstParMMenuNum))
  501.                 || (ParMMode == MODE_CLI && Class == CLOSEWINDOW))
  502.             {
  503.                 if (Class == 0x0FL)        /* Msg sent bye 'ParMCD' command */
  504.                     ChangeDir((char *)IMsg->IAddress);
  505.                 ReplyMsg((struct Message *)IMsg);
  506.             }
  507.             else {
  508.                 PutMsg(&SwapPort, (struct Message *)IMsg);
  509.                 if (Class == NEWPREFS) {
  510.                     while (LastWBMenu->NextMenu)
  511.                         Delay(10);
  512.                     InstallWBMenus(&Menu1);
  513.                 }
  514.                 continue;    /* Don't handle these messages */
  515.             }
  516.             switch (Class) {
  517.             case CLOSEWINDOW:
  518.                 quit = TRUE;
  519.                 break;
  520.             case REFRESHWINDOW:
  521.                 if (RefreshIt) {
  522.                     if (IsHidden(Win)) {
  523.                         WindowToFront(Win);
  524.                         RefreshIt = FALSE;    /* prevent refresh caused by WindoToFront() */
  525.                     }
  526.                 }
  527.                 else
  528.                     RefreshIt = TRUE;
  529.                 break;
  530.             case MENUPICK:
  531.                 DoNextSelect = TRUE;
  532.                 if (Code != MENUNULL) {
  533.                     if (ParMMode == MODE_WINDOW)
  534.                         Busy(TRUE);
  535.                     do {
  536.                         /* Prevent extended selection of workbench menus */
  537.                         if (MENUNUM(Code) == FirstParMMenuNum) {
  538.                             switch(ITEMNUM(Code)) {
  539.                             case OPEN_ITEM:
  540.                                 OpenMenus();
  541.                                 DoNextSelect = FALSE;
  542.                                 break;
  543.                             case UPDATE_ITEM:
  544.                                 UpDateMenus();
  545.                                 DoNextSelect = FALSE;
  546.                                 break;
  547.                             case STD_CFG_ITEM:
  548.                                 strcpy(ParMConfig.CurCfg, DEFAULT_CONFIG_FILE);
  549.                                 UpDateMenus();
  550.                                 DoNextSelect = FALSE;
  551.                                 break;
  552.                             case CMDMODE_ITEM:
  553.                                 ParMConfig.SimpleCmdMode = SubItem1.Flags & CHECKED;
  554.                                 break;
  555.                             case COMMAND_ITEM:
  556.                                 Command(&ParMConfig);
  557.                                 break;
  558.                             case CHDIR_ITEM:
  559.                                 PathName(ParMProcess->pr_CurrentDir, Dir, REQ_DSIZE);
  560.                                 FileReq.Flags = FRQDIRONLYM;
  561.                                 FileReq.Title = "Enter New Dir...";
  562.                                 if (FileRequester(&FileReq))
  563.                                     ChangeDir(Dir);
  564.                                 FileReq.Flags = 0;
  565.                                 break;
  566.                             case QUIT_ITEM:
  567.                                 quit = TRUE;
  568.                                 DoNextSelect = FALSE;
  569.                             }
  570.                         }
  571.                         else if (MENUNUM(Code) > FirstParMMenuNum)    /* custom menus */
  572.                             DoExtMenu(Code);
  573.                     } while (DoNextSelect && (Code = ItemAddress(TheMenu, Code)->NextSelect) != MENUNULL);
  574.                     if (ParMMode == MODE_WINDOW)
  575.                         Busy(FALSE);
  576.                 }
  577.                 break;
  578.             }
  579.         }
  580.         /* See if some wb messages have been replied, and free them */
  581.         FreeRepliedWBMessages();
  582.     }
  583.     Bye(THE_END);
  584. }
  585.  
  586.  
  587.